const request = require('superagent');
require('superagent-proxy')(request);
const UserAuth = require('./auth');
module.exports = {
    // 模块介绍
    summary: 'my customized rule for AnyProxy',
    // 发送请求前拦截处理
    async beforeSendRequest(requestDetail) {
        if(requestDetail.requestOptions.hostname.indexOf("google")>=0)
            return {
                response: {
                    statusCode: 500,
                    header: { 'content-type': 'application/json; charset=utf-8' },
                    body: '{"code":10001, "msg":"不可访问海外网站"}'
                }
            };
        let header = requestDetail.requestOptions.headers;
        let authorization = header.Authorization ? header.Authorization : (header.authorization ? header.authorization : null);
        if(!authorization){
            return {
                response: {
                    statusCode: 500,
                    header: { 'content-type': 'application/json; charset=utf-8' },
                    body: '{"code":10002, "msg":"头部没有 Authorization 信息，无法通过请求"}'
                }
            };
        } else {
            delete requestDetail.requestOptions.headers.Authorization;
            delete requestDetail.requestOptions.headers.authorization;
        }

        let url = `${requestDetail.protocol}://${requestDetail.requestOptions.hostname}${requestDetail.requestOptions.path}`;
        let userAuth = new UserAuth(authorization, url);
        let returnBody = null, proxyInfo, isError = false;
        let isResource = false;
        try{
            if(!await userAuth.checkIt())
                return {
                    response: {
                        statusCode: 500,
                        header: { 'content-type': 'application/json; charset=utf-8' },
                        body: '{"code":10003, "msg":"Authorization 信息错误，无法通过请求"}'
                    }
                };
            if(!await userAuth.checkPack())
                return {
                    response: {
                        statusCode: 500,
                        header: { 'content-type': 'application/json; charset=utf-8' },
                        body: '{"code":10004, "msg":"无可用套餐且余额不足"}'
                    }
                };
            let host = requestDetail.requestOptions.hostname.replace(/\./g,"|");
            let cacheUrl = requestDetail.requestOptions.headers.Referer || url;
            proxyInfo = await sesame.getProxyIP(host, url, cacheUrl);
            // console.log("proxyInfo", JSON.stringify(proxyInfo));
            if (requestDetail.requestOptions.path.match(/(\.ico|\.png|\.css|\.gif|\.jpg|\.ttf|\.woff|\.ogg|\.mp3|@!fill)/)) isResource = true;
            let isCache = await userAuth.isCache(url, requestDetail.requestOptions.method);
            if (isCache) return isCache.response;
            if(!isResource) isResource = await userAuth.isFilter(url);
            requestDetail.requestOptions.isResource = isResource;
            requestDetail.requestOptions.userAuth = userAuth;
            if(!isResource) console.log("proxyInfo", url, isResource);
            if(!isResource) {
                requestDetail.requestOptions.requestInfo = { headers: requestDetail.requestOptions.headers };
                if(requestDetail.requestOptions.method === "GET"){
                    try {
                        let response = await request("GET",url).set(requestDetail.requestOptions.headers)
                            .proxy(`http://${proxyInfo.ip}:${proxyInfo.port}`).timeout(30 * 1000).buffer(true);
                        delete response.headers['content-encoding'];
                        returnBody = {
                            response: {
                                statusCode: response.statusCode,
                                header: response.headers,
                                body: response.text
                            }
                        };
                        return returnBody;
                    } catch(e){
                        if(e.response){
                            returnBody = {
                                response: {
                                    statusCode: e.response.statusCode,
                                    header: e.response.headers,
                                    body: e.response.text
                                }
                            };
                            return returnBody;
                        } else {
                            if(proxyInfo) console.error('proxy GET', url, `http://${proxyInfo.ip}:${proxyInfo.port}`, e.message);
                            if(
                                e.message.indexOf("connect ETIMEDOUT") >= 0
                                || e.message.indexOf("connect ECONNREFUSED") >= 0
                                || e.message.indexOf("read ECONNRESET") >= 0
                                || e.message.indexOf("Timeout") >= 0
                            ) await sesame.removeIP(proxyInfo.ip, proxyInfo.port);
                            isError = true;
                            requestDetail.requestOptions.message = e.message;
                            return null;
                        }
                    }
                } else if(requestDetail.requestOptions.method === "POST" ) {
                    let type = null, data = {};
                    try{
                        switch(requestDetail.requestOptions.headers["Content-Type"]){
                            case "application/x-www-form-urlencoded; charset=UTF-8":
                            case "application/x-www-form-urlencoded":
                                type = 'form';
                                let str = requestDetail.requestData.toString();
                                let array = str.split("&");
                                for(let kv of array){
                                    let obj = kv.split("=");
                                    let k = obj.splice(0,1);
                                    data[k[0]] = obj.join("=");
                                }
                                break;
                            case "application/json; charset=UTF-8":
                            case "application/json":
                                type = 'json';
                                data = JSON.parse(requestDetail.requestData.toString());
                                break;
                        }
                        requestDetail.requestOptions.requestInfo.type = type;
                        requestDetail.requestOptions.requestInfo.data = data;
                        if(type){
                            let response = await request("POST",url).set(requestDetail.requestOptions.headers).type(type).send(data)
                                .proxy(`http://${proxyInfo.ip}:${proxyInfo.port}`).timeout(30 * 1000).buffer(true);
                            delete response.headers['content-encoding'];
                            returnBody = {
                                response: {
                                    statusCode: response.statusCode,
                                    header: response.headers,
                                    body: response.text
                                }
                            };
                            return returnBody;
                        } else {
                            isError = true;
                            requestDetail.requestOptions.message = "not post type";
                            return null
                        }
                    } catch(e){
                        if(e.response){
                            returnBody = {
                                response: {
                                    statusCode: e.response.statusCode,
                                    header: e.response.headers,
                                    body: e.response.text
                                }
                            };
                            return returnBody;
                        } else {
                            if(
                                e.message.indexOf("connect ETIMEDOUT") >= 0
                                || e.message.indexOf("connect ECONNREFUSED") >= 0
                                || e.message.indexOf("read ECONNRESET") >= 0
                                || e.message.indexOf("Timeout") >= 0
                            ) await sesame.removeIP(proxyInfo.ip, proxyInfo.port);
                            if(proxyInfo) console.error('proxy post', url, `http://${proxyInfo.ip}:${proxyInfo.port}`, e.message, type, requestDetail.requestOptions.headers);
                            isError = true;
                            requestDetail.requestOptions.message = e.message;
                            return null;
                        }
                    }
                } else {
                    isError = true;
                    requestDetail.requestOptions.message = "not http method";
                    return null
                }
            } else {
                return null;
            }
        }catch(e){
            isError = true;
            console.error(e)
        } finally {
            //用户消费记录
            if(!isError && returnBody){
                await userAuth.newRecord(url, requestDetail.requestOptions.method, returnBody.response.statusCode, returnBody.response.header, returnBody.response.body, proxyInfo, requestDetail.requestOptions.requestInfo );
                await sesame.fixedRecord(proxyInfo);
            } else{
                await userAuth.fail();
            }
        }
    },
    // 发送响应前处理
    async beforeSendResponse(requestDetail, responseDetail) {
        let url = `${requestDetail.protocol}://${requestDetail.requestOptions.hostname}${requestDetail.requestOptions.path}`;
        if(requestDetail.requestOptions.message){
            await requestDetail.requestOptions.userAuth.newRecord(url, requestDetail.requestOptions.method, responseDetail.response.statusCode, responseDetail.response.header, responseDetail.response.body.toString(), null, requestDetail.requestOptions.requestInfo);
        }
        if (requestDetail.requestOptions.isResource) {
            await requestDetail.requestOptions.userAuth.cache(
                url
                , requestDetail.requestOptions.method
                , {
                    statusCode: responseDetail.response.statusCode,
                    header: responseDetail.response.header,
                    body: responseDetail.response.body
                }
                , responseDetail.response.body.toString().length
            )
        }
    },
    // 是否处理https请求
    *beforeDealHttpsRequest(requestDetail) {
        return true
    },
    // 请求出错的事件
    async onError(requestDetail, error) {
        console.error("onError", error.message);
        if(
            error.message.indexOf("ETIMEDOUT") >= 0
                || error.message.indexOf("ECONNREFUSED") >= 0
                || error.message.indexOf("ECONNRESET") >= 0
                || error.message.indexOf("Timeout") >= 0
            ) await sesame.removeIP(requestDetail.requestOptions.hostname, requestDetail.requestOptions.port);
        return {
            response: {
                statusCode: 200,
                header: { 'content-type': 'text/html;charset=utf-8' },
                body: '请求出错'
            }
        };
    },
    // https连接服务器出错
    async onConnectError(requestDetail, error) {
        console.error("onConnectError", error);
        if(requestDetail.requestOptions.message){
            await requestDetail.requestOptions.userAuth.fail();
        }
        return {
            response: {
                statusCode: 500,
                header: { 'content-type': 'text/html;charset=utf-8' },
                body: '请求出错'
            }
        };
    }
};